﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Entities.Portals;
using DotNetNuke.Entities.Tabs;
using DotNetNuke.Security;
using DotNetNuke.Security.Permissions;
using System.Text.RegularExpressions;

namespace DNNspot.Sitemap
{
    public class ModuleBase : PortalModuleBase
    {
        public bool _ShowHiddenMenuItems = false;
        public bool _ShowViewEditPermissions = false;
        public int _SitemapLevel = 0;
        public int _SitemapStart = 0;
        public int _PortalId;
        public string[] _ExcludedTabs;
        public string[] _IncludedTabs;
        public string _PortalAlias;
        
        public string WriteTab(int start, bool hasChildren, int portalId, string portalAlias, TabInfo currentTab)
        {
            TabController tabcontroller = new TabController();
            ArrayList allTabs = tabcontroller.GetTabsByParentId(start, portalId);

            string taboutput = "";

            foreach (TabInfo tab in allTabs)
            {

                if (tab.TabName == "Happenings")
                {
                    var test = "test";
                }

                if (tab.Level >= _SitemapLevel && _SitemapLevel != 0)
                    return "";

                List<TabInfo> childrenTabs = tabcontroller.GetTabsByParentId(tab.TabID, portalId).Cast<TabInfo>().ToList();
                var currentTabBreadcrumbs = currentTab.BreadCrumbs.Cast<TabInfo>().ToList();
                bool isActivePath = currentTabBreadcrumbs.Any(t => t.TabID == tab.TabID);

                try
                {
                    if(tab.BreadCrumbs != null)
                    {
                        var parentBreadcrumbs = tab.BreadCrumbs.Cast<TabInfo>().ToList().TakeWhile(t => _IncludedTabs.Any(it => it == t.TabID.ToString()));
                        if (!_IncludedTabs.Any(t => tab.TabID.ToString() == t) && !parentBreadcrumbs.Any(pb => tab.TabID == pb.TabID))
                            continue;
                    }
                    else
                    {
                        if (_IncludedTabs != null && !_IncludedTabs.Any(t => tab.TabID.ToString() == t))
                        {
                            continue;
                        }

                    }


                }
                catch(Exception e)
                {
                    
                }

                if (tab.IsDeleted == false && ((tab.IsVisible == true) || (_ShowHiddenMenuItems == true && tab.IsVisible == false)))
                {

                    bool isAllUser = CanView(tab);

                    if (isAllUser)
                    {
                        string tabPath = tab.FullUrl;
                        var tabType = tab.TabType;
                        if (!String.IsNullOrEmpty(portalAlias))
                        {
                            if (tab.TabType == TabType.File)
                            {
                                tabPath = "http://" + portalAlias + "/LinkClick.aspx?fileticket=" + EncryptFileUrl(UrlUtils.GetParameterValue(tab.Url), portalId);
                            }
                            else if (tab.TabType == TabType.Normal || tab.TabType == TabType.Tab)
                            {
                                //OLD WAY TO REPLACE PORTAL ALIAS
                                //string oldTab = tabName.Replace("http://", String.Empty).Replace("https://", String.Empty);
                                //int firstSlash = oldTab.IndexOf("/");
                                //tabName = tabName.Replace(oldTab.Substring(0, firstSlash), portalAlias);

                                //USE DIFFERENT PORTAL ALIAS
                                tabPath = tabPath.Replace(PortalAlias.HTTPAlias, portalAlias);
                            }

                        }

                        //DotNetNuke.Common.Globals.LinkClick()

                        string selectedTabClass = String.Empty;
                        if (currentTab.TabID == tab.TabID)
                        {
                            selectedTabClass = " SelectedTab";
                        }

                        string viewPermissions = String.Empty;
                        if (_ShowViewEditPermissions)
                        {
                            viewPermissions = String.Format(" - View: {0} | Edit: {1}", tab.AuthorizedRoles.TrimEnd(';').Replace(";", ", "), tab.AdministratorRoles.TrimEnd(';').Replace(";", ", "));
                        }

                        var test = tab.BreadCrumbs;
                        const string tabPermissionPrepend = "TabPermission_";
                        string viewPermissionsClass = tabPermissionPrepend + tab.AuthorizedRoles.Replace(" ", String.Empty).TrimEnd(';').Replace(";", " " + tabPermissionPrepend).Replace("!", "Not");
                        
                        string activePathClass = String.Empty;
                        if (isActivePath)
                        {
                            activePathClass = "SelectedTabNode";
                        }

                        string tabNameClass = Regex.Replace(tab.TabName, "[^0-9a-zA-Z]", "");
                            

                        taboutput += String.Format("<li class=\"li-level{0} {1}{2} {3} {4}\">\n<a href=\"{5}\" title=\"{6}\">{7}</a>{8}\n", tab.Level, tabNameClass, selectedTabClass, viewPermissionsClass, activePathClass, tabPath, tab.Title, tab.TabName, viewPermissions);


                        bool isDeleted = true;
                        foreach (TabInfo t in childrenTabs)
                        {
                            isDeleted = t.IsDeleted;
                            if (!isDeleted)
                            {
                                break;
                            }
                        }

                        if (tab.HasChildren && !isDeleted)
                        {
                            taboutput += "<ul class=\"ul-level" + tab.Level + "\">";
                            taboutput += WriteTab(tab.TabID, true, portalId, portalAlias, currentTab);
                            taboutput += "</ul>";
                        }

                        taboutput += "</li>";

                        hasChildren = false;
                    }
                }
            }//for each
            return taboutput;
        }

        private static string EncryptFileUrl(string url, int portalId)
        {
            var portal = new PortalController();
            var portalSettings = portal.GetPortal(portalId);

            PortalSecurity portalSecurity = new PortalSecurity();
            var strParameter = portalSecurity.Encrypt(portalSettings.GUID.ToString(), url);

            //'[DNN-8257] - Can't do URLEncode/URLDecode as it introduces issues on decryption (with / = %2f), so we use a modifed Base64
            strParameter = strParameter.Replace("/", "_");
            strParameter = strParameter.Replace("+", "-");
            strParameter = strParameter.Replace("=", "%3d");
            return strParameter;
        }

        bool CanView(TabInfo tab)
        {

            //CHECK TO SEE IF IT IS EXCLUDED
            if (_ExcludedTabs != null)
            {
                if (_ExcludedTabs.Count() > 0)
                {
                    if (_ExcludedTabs.Any(tabid => tabid == tab.TabID.ToString()))
                    {
                        return false;
                    }
                }
            }

            //ADMINS Can see anything
            if ((IsEditable || UserInfo.IsSuperUser || UserInfo.IsInRole("Administrators")))
                return true;

            //
            TabPermissionCollection tpc = tab.TabPermissions;

            if (UserId > 0) //USER IS LOGGED IN
            {
                return tpc.Cast<TabPermissionInfo>().Where(tpi => tpi.PermissionName == "View Tab").Any(tpi => PortalSecurity.IsInRole(tpi.RoleName));
            }
            else  //USER IS PUBLIC
            {
                return tpc.Cast<TabPermissionInfo>().Any(tpi => tpi.RoleName == "All Users" && tpi.PermissionName == "View Tab");
            }
            return false;
        }



        public string GenerateSitemap(TabInfo currentTab)
        {
            return "<ul class=\"DNNspot-sitemap\"> \n" + WriteTab(_SitemapStart, true, _PortalId, _PortalAlias, currentTab) + "</ul>";
        }

        public string DumpRawData()
        {
            TabController tabcontroller = new TabController();
            ArrayList alltabs = tabcontroller.GetTabs(PortalId);
            string dataOutput = String.Empty;

            foreach (TabInfo tab in alltabs)
            {
                dataOutput += " FullUrl:" + tab.FullUrl + " HasChildren:" + tab.HasChildren + " IsDeleted" + tab.IsDeleted + " IsVisible:" + tab.IsVisible + "  Level" + tab.Level + " ParentId:" + tab.ParentId + " TabName:" + tab.TabName + " Title:" + tab.Title + " Url:" + tab.Url + " <br/>";
                //sitemapOutput.Text += tab.TabPermissions.ToString()+"<br/>";
                TabPermissionCollection tpc = tab.TabPermissions;

                dataOutput = tpc.Cast<TabPermissionInfo>().Aggregate(dataOutput, (current, tpi) => current + (tpi.PermissionName + " " + tpi.RoleName + "<br/>"));
            }

            return dataOutput;
        }
    }
}